import 'package:flutter/material.dart';

/// 评分组件
class StarRating extends StatefulWidget {
  /// 分数
  final double rating;

  /// 总分
  final double maxRating;

  /// 用几颗星显示
  final int count;

  /// 星星的大小
  final double size;

  /// 空星的颜色
  final Color unselectedColor;

  /// 实星的颜色
  final Color selectedColor;

  /// 空星的组件
  final Widget unselectedImage;

  /// 实星的组件
  final Widget selectedImage;

  StarRating(
    this.rating, {
    this.maxRating = 10,
    this.count = 5,
    this.size = 30,
    this.unselectedColor = Colors.yellow,
    this.selectedColor = Colors.red,
    Widget? unselectedImage,
    Widget? selectedImage,
  })  : unselectedImage = unselectedImage ?? Icon(Icons.star_border, color: unselectedColor, size: size),
        selectedImage = selectedImage ?? Icon(Icons.star, color: selectedColor, size: size);

  @override
  State<StarRating> createState() => _StarRatingState();
}

class _StarRatingState extends State<StarRating> {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Row(mainAxisSize: MainAxisSize.min, children: buildUnSelectedStar()),
        Row(mainAxisSize: MainAxisSize.min, children: buildSelectedStar())
      ],
    );
  }

  List<Widget> buildUnSelectedStar() {
    return List.generate(widget.count, (index) => widget.unselectedImage);
  }

  List<Widget> buildSelectedStar() {
    var rating = widget.rating;
    if (widget.rating > widget.maxRating) {
      rating = widget.maxRating;
    }

    double rate = widget.maxRating / widget.count;
    double wholeNum = rating / rate;
    int pointPre = (wholeNum).floor();
    double pointNext = (wholeNum) - pointPre;

    List<Widget> stars = List.generate(pointPre, (index) => widget.selectedImage);

    // 通过裁剪来做到不完整的星星
    stars.add(ClipRect(clipper: _MyStarClipper(pointNext * widget.size), child: widget.selectedImage));

    return stars;
  }
}

class _MyStarClipper extends CustomClipper<Rect> {
  final double width;

  _MyStarClipper(this.width);

  @override
  Rect getClip(Size size) {
    return Rect.fromLTRB(0, 0, width, size.height);
  }

  @override
  bool shouldReclip(_MyStarClipper oldClipper) {
    return oldClipper.width != width;
  }
}
